﻿GUI = function() {}

/*
    Questa classe funge da proxy locale per le interrogazioni al server di loa.
*/
GUI.AAANetUtils = function()
{
    this._requestStatus = 0;    // stato della richiesta (i vari stati sono elencati al termine del file)
    this._requestResult = null; // risultato della richiesta
    this._counter = 0;
};

GUI.AAANetUtils.prototype = {

    // ------------------ public functions ----------------------------------------------------
    /*
        Effettua una chiamata ad un webservice sul server di loa. I parametri sono:
        - type = tipo della richiesta (tra quelli registrati)
        - params = array che contiene i parametri della richiesta
        - ok_callback = funzione di callback richiamata se tutto va a buon fine, passando
            il risultato della richiesta
        - dontJoinArray = se il ws riceve come unico parametro un array e dontJoinArray
            è settato a true, indica di non considerare il parametro <params> 
            come un array di parametri ma come un solo parametro array
    */
    performRequest: function(type, params, ok_callback, err_callback, dontJoinArray)
    {
        // ricava la stringa della richiesta in funzione del parametro <type>...
        var _req = GUI.AAANetUtils._requests[type];
        var _params = null;
        
        // ...costruisce la stringa dei parametri in funzione del parametro <params>
        // applicando le convenzioni descritte in precedenza...
        if (params !== null)
        {
            if (dontJoinArray && dontJoinArray == true)
            {
                _params = 'params';
            }else{
                if (params.constructor.toString().indexOf("Array") == -1)
                {
                    // only one parameter
                    _params = params;
                }else 
                {
                    // more than one parameter
                    _params = params.join(', ');
                }
            }
            _params += ', ';
        }else 
        {
            // no parameters
            _params = "";
        }
        
        // ...completa la richiesta...
        _req = _req.replace("<params>", _params);
        
        // ...e la effettua.
        eval(_req);
    },
    
    // --------------------------------------------------------------------------------

    // --------------- properties -----------------------------------------------------
    getRequestStatus: function()
    {
        return (this._requestStatus);
    },
    
    getRequestResult: function()
    {
        return (this._requestResult);
    },
    // -------------------------------------------------------------------------------
    
    
    // --------------- webservices callbacks -----------------------------------------
    // callbacks per le interrogazioni al server di loa.
    _onRequestSuccess: function(result, cback_arr, methodName)
    {
        // in caso di successo si invoca la funzione di callback passando il risultato
        this._requestResult = result;
        this._requestStatus = 0;
        cback_arr[0](result);
    },
    
    _onRequestFailure: function(error, cback_arr, methodName)
    {
        // altrimenti si gestiscono gli eventuali errori (per ora si stampano)
        this._requestResult = error;
        this._requestStatus = 1;
        cback_arr[1](error);
    }
    // -------------------------------------------------------------------------------
};

// tipi di richieste possibili al server di loa
GUI.AAANetUtils.GEOCODING_REQUEST = 0;

// stringhe di richiesta associate ai vari tipi di richiesta.
// notare il placemark <params> in corrispondenza dei parametri della richiesta.
GUI.AAANetUtils._requests = new Array(
    "TripLOA.WebService.georef_test_2.WSGeoRef.geoCoding(<params> this._onRequestSuccess, this._onRequestFailure, [ok_callback, err_callback])"
);



/* A control used to show a menu with ambiguous geocoding results */
/*Constructor of Menu. It takes a textbox reference and optionally
two constants which specified horizontal and vertical position of
menu respect to the control*/
GUI.AAAGeoCodingMenu = function(inputControl, menuLR, menuUD) {
    //sets default positions
    if (menuLR == "undefined" || (menuLR != GUI.AAAGeoCodingMenu.LEFT && menuLR != GUI.AAAGeoCodingMenu.RIGHT)) {
        menuLR = GUI.AAAGeoCodingMenu.RIGHT;
    }
    if (menuUD == "undefined" || (menuUD != GUI.AAAGeoCodingMenu.UP && menuUD != GUI.AAAGeoCodingMenu.DOWN)) {
        menuUD = GUI.AAAGeoCodingMenu.DOWN;
    }
    
    //default values
    createChooseLocation();
    inputControl.latitude = "-1";
    inputControl.longitude = "-1";
    //Property in which store handler of custom events for Internet Explorer
    inputControl.status_handler = null;
    inputControl.maxVisibleItems = 6;
    inputControl.timerId = 0;
    
    inputControl.oldValue = "";
    
    /*Performs geocoding operation if this is enabled in the textbox, linked to
      onblur event of the control*/
    inputControl.geoCode = function() {
        if (inputControl.value != "" && inputControl.enabledGeocoding == true) {            
            var netUtils = new GUI.AAANetUtils();
            inputControl.changeStatus(GUI.AAAGeoCodingMenu.FILLED);
            netUtils.performRequest(GUI.AAANetUtils.GEOCODING_REQUEST, '"'+inputControl.value+'"', inputControl.geoCodingOk, inputControl.geoCodingFail);
        } else if (inputControl.value == ""){
            inputControl.latitude = "-1";
            inputControl.longitude = "-1";
            inputControl.changeStatus(GUI.AAAGeoCodingMenu.EMPTY);
        } 
    }
    
    //Enables geocoding operations
    inputControl.enableGeocoding = function(value) {
        if (value == true || value == false) {
            inputControl.enabledGeocoding = value;
        }
    }
        
    //Associates each event handler to the correspondent event
    inputControl.onblur = inputControl.geoCode;
    inputControl.onchange = function() {
        inputControl.enableGeocoding(true);
    }
    
    //On keydown event hides the menu if is already shown
    inputControl.onkeydown = function() {        
        if (inputControl.menuStatus == 1) {            
            inputControl.hideMenu();
        }
    }
    
    //On keyup event changes the menu status
    inputControl.onkeyup = function() {
        if (inputControl.value.length == 0) {
            inputControl.changeStatus(GUI.AAAGeoCodingMenu.EMPTY);
        } else if (inputControl.value != inputControl.oldValue) {
            inputControl.changeStatus(GUI.AAAGeoCodingMenu.FILLED);
        } 
    }
    
    //Fires up event when the control changes status, and so saves it
    inputControl.changeStatus = function(updatedStatus) {
        if (updatedStatus != inputControl.controlstatus) {
            if (document.all) {
                var event = document.createEventObject();
                event.target = inputControl;
                event.srcElement = inputControl;                
            } else {    
                var event = document.createEvent("Event");
                event.initEvent("statusChanged", false, false); //no bubble up, no cancelable
            }
            
            event.controlStatus = updatedStatus;
            inputControl.controlstatus = updatedStatus;
            if (document.all) {
                
                if (inputControl.status_handler != null) {
                    inputControl.status_handler(event);              
                }
                
                inputControl.onstatusChanged = event;
            } else {
                inputControl.dispatchEvent(event);
            }
        }
    }
    
    //Handles event of changeStatus
    inputControl.statusHandler = function(function_name) {
        if (document.all) { //explorer
            inputControl.status_handler = function_name;
        } else {
            document.addEventListener("statusChanged", function_name, true);
        }
    }
    
    
    /*Fills the menu according the results of geocoding query. If error is present
      it will show an error message instead of correct results*/
    inputControl.geoCodingOk = function(result) {
        chooseLocation = document.getElementById(inputControl.id + "_chLoc");
        if (result && result != null) {
            if (result.length > 1) { //more than one result of geocoding query
                var listBox = chooseLocation.firstChild;
                inputControl.resetListBox();
                for (i = 0; i < result.length; i++) {
                    inputControl.addListItem(result[i]);
                }
                if (result.length > inputControl.maxVisibleItems) {//show scrollbar: results > set max rows of menu
                    //gets single item height and so sets menu box height
                    var itemHeight = listBox.firstChild.clientHeight > 0 ? listBox.firstChild.clientHeight : listBox.firstChild.offsetHeight;
                    chooseLocation.style.height = (inputControl.maxVisibleItems * itemHeight) + "px";
                    //show scrollbar
                    chooseLocation.style.paddingRight = "18px";
                    document.getElementById(inputControl.id + "_scrollBar").style.top = "0";
                } else {//no scrollbar: results <= set max rows of menu
                    //sets menu box height to "auto"
                    chooseLocation.style.height = "auto";
                    //hide scrollbar
                    chooseLocation.style.paddingRight = "0";
                    document.getElementById(inputControl.id + "_scrollBar").style.top = "-10000px";
                }
                inputControl.showMenu();                
            } else if (result.length == 1) { //only one result of geocoding query
                inputControl.value = result[0].Address;
                inputControl.latitude = result[0].Lat;
                inputControl.longitude = result[0].Lng;
                inputControl.enableGeocoding(false);
                inputControl.changeStatus(GUI.AAAGeoCodingMenu.READY);
                inputControl.oldValue = inputControl.value;
                //sets menu box height to "auto"
                chooseLocation.style.height = "auto";
            } else {  //query produces error              
                inputControl.changeStatus(GUI.AAAGeoCodingMenu.ERROR);
                inputControl.resetListBox();
                var errorMsg = {"Address":inputControl.locNotFound};
                inputControl.addListItem(errorMsg);
                var elem = document.getElementById(inputControl.id + "_chLoc_ListBox").firstChild;
                elem.style.color = "#ff0000";
                elem.onclick = ""; //disable click event on error msg
                elem.onmouseover = ""; //disable mouse events
                elem.onmouseout = ""; //disable mouse events
                //sets menu box height to "auto"
                chooseLocation.style.height = "auto";
                //hides scrollbar
                chooseLocation.style.paddingRight = "0";
                document.getElementById(inputControl.id + "_scrollBar").style.top = "-10000px";
                //shows menu
                inputControl.showMenu();
                inputControl.latitude = "-1";
                inputControl.longitude = "-1";
            }
        }
    }
    
    inputControl.setGeoloc = function(geoloc)
    {
        inputControl.oldValue = inputControl.value;
        inputControl.value = geoloc.address;
        inputControl.latitude = geoloc.lat;
        inputControl.longitude = geoloc.lng;
        inputControl.enableGeocoding(false);
        inputControl.changeStatus(GUI.AAAGeoCodingMenu.READY);        
    }
    
    //GeoCoding operation is failed for some reason (i.e url isn't reachable)
    inputControl.geoCodingFail = function() {
        inputControl.changeStatus(GUI.AAAGeoCodingMenu.ERROR);
        chooseLocation = document.getElementById(inputControl.id + "_chLoc");
        inputControl.resetListBox();
        var errorMsg = {"Address": inputControl.geocodeFail};
        inputControl.addListItem(errorMsg);
        var elem = document.getElementById(inputControl.id + "_chLoc_ListBox").firstChild;
        elem.style.color = "#ff0000";
        elem.onclick = ""; //disable click event on error msg
        elem.onmouseover = ""; //disable mouse events
        elem.onmouseout = ""; //disable mouse events
        //sets menu box height to "auto"
        document.getElementById(inputControl.id + "_chLoc").style.height = "auto";
        //hides scrollbar
        chooseLocation.style.paddingRight = "0";
        document.getElementById(inputControl.id + "_scrollBar").style.top = "-10000px";
        //shows menu
        inputControl.showMenu();
        inputControl.latitude = "-1";
        inputControl.longitude = "-1";
    }
    
    //Clear box of menu from previous values and reset position
    inputControl.resetListBox = function() {
        var listBox = document.getElementById(inputControl.id + "_chLoc_ListBox");
        if (listBox.hasChildNodes()) {
            while (listBox.childNodes.length >= 1) {
                listBox.removeChild(listBox.firstChild);
            }
        }
        listBox.style.top = "0";
    }
    
    //Adds a single geoloc object to the listbox of menu, and sets its properties
    inputControl.addListItem = function(geoloc) {
        var listBox = document.getElementById(inputControl.id + "_chLoc_ListBox");
        var listItem = document.createElement("li");
        //Appends address and coordinates of geoloc to listbox
        listItem.innerHTML = geoloc.Address;
        listItem.latitude = geoloc.Lat;
        listItem.longitude = geoloc.Lng;
        listItem.style.padding = "2px";
        listItem.style.cursor = "pointer";
        
        //stored in textbox the selected item with its properties, and hides menu
        listItem.onclick = function() {
            inputControl.value = listItem.innerHTML;
            inputControl.latitude = listItem.latitude;
            inputControl.longitude = listItem.longitude;
            inputControl.enableGeocoding(false);
            inputControl.changeStatus(GUI.AAAGeoCodingMenu.READY);
            inputControl.oldValue = inputControl.value;
            inputControl.hideMenu();
        }
        
        //invertes colours when the mouse is over the item
        listItem.onmouseover = function() {
            listItem.style.background = bckgrHighColour;
            listItem.style.color = txtHighColour;
            bckgrHighColour;
        }
        
        //resets colours when the mouse leaves the item
        listItem.onmouseout = function() {
            listItem.style.background = backGrColour;
            listItem.style.color = txtColour;
            bckgrHighColour;
        }
        listBox.appendChild(listItem);
    }
    
    //Makes the menu visible
    inputControl.showMenu = function() {
        inputControl.setHorizontalPos(menuLR);
        inputControl.setVerticalPos(menuUD);
        inputControl.setScrollerHeightAndStep();
        var menuBox = document.getElementById(inputControl.id + "_chLoc");
        menuBox.style.top = menuBox.visibleY + "px";
        menuBox.style.left = menuBox.visibleX + "px";
        //menuBox.style.display = "block";
        inputControl.menuStatus = 1;
    }
    
    //Makes the menu hidden
    inputControl.hideMenu = function() {
        var menuBox = document.getElementById(inputControl.id + "_chLoc");
        menuBox.style.top = "-10000px";
        menuBox.style.left = "-10000px";
        //menuBox.style.display = "none";
        inputControl.menuStatus = 0;
    }
    
    //Positions the menu in the right side (left or right) according to the parameter
    inputControl.setHorizontalPos = function(side) {
        if (side != "undefined" && (side == GUI.AAAGeoCodingMenu.LEFT || side == GUI.AAAGeoCodingMenu.RIGHT)) {
            var container = document.getElementById(inputControl.id + "_chLoc");
            var inputPosition = elementPosition(inputControl);
            if (menuLR == GUI.AAAGeoCodingMenu.RIGHT) {
                container.visibleX = inputPosition.x + inputControl.clientWidth + 4;
            } else {
                container.visibleX = inputPosition.x - container.clientWidth;
            }
        }
    }
    
    //Positions the menu in the right direction (up or down) according to the parameter
    inputControl.setVerticalPos = function(dir) {
        if (dir != "undefined" && (dir == GUI.AAAGeoCodingMenu.UP || dir == GUI.AAAGeoCodingMenu.DOWN)) {
            var container = document.getElementById(inputControl.id + "_chLoc");
            var inputPosition = elementPosition(inputControl);
            if (menuUD == GUI.AAAGeoCodingMenu.DOWN) {
                container.visibleY = inputPosition.y + 2;
            } else {
                container.visibleY = inputPosition.y - container.clientHeight + inputControl.clientHeight + 4;
            }
        }
    }
    
    inputControl.setScrollerHeightAndStep = function() {
        var container = document.getElementById(inputControl.id + "_chLoc");
        var listBox = container.firstChild;
        var slider = document.getElementById(inputControl.id + "_scrollBar_slider");
        var itemHeight = listBox.getElementsByTagName("li").item(0).offsetHeight;
        var overflowItems = listBox.getElementsByTagName("li").length - inputControl.maxVisibleItems;
        var maxSliderHeight = container.offsetHeight - 
                              slider.nextSibling.offsetHeight - slider.previousSibling.offsetHeight - 1;
        var sliderHeight = maxSliderHeight - (overflowItems * itemHeight);
        if (sliderHeight < 4) sliderHeight = 4;
        slider.style.height = sliderHeight + "px";
        slider.style.top = slider.previousSibling.height + "px";
        slider.stepSize = (maxSliderHeight - sliderHeight) / overflowItems;
        slider.stepSize.toFixed(1);
    }
    
    //Sets colours of background and text when an item is highlighted
    inputControl.SetHighlightColours = function(text, background) {
        if (text.charAt(0) == '#' && (text.length == 4 || text.length == 7)) {
            txtHighColour = text;
        }
        
        if (background.charAt(0) == '#' && (background.length == 4 || background.length == 7)) {
            bckgrHighColour = background;
        }               
        
    }
    
    //Sets colours of background and text when an item is not highlighted
    inputControl.SetColours = function(text, background) {
        var container = document.getElementById(inputControl.id + "_chLoc");
        var listbox = container.firstChild;
        if (text.charAt(0) == '#' && (text.length == 4 || text.length == 7)) {
            txtColour = text;
            container.style.color = txtColour;
            listbox.style.color = txtColour;
        }
        if (background.charAt(0) == '#' && (background.length == 4 || background.length == 7)) {
            backGrColour = background;
            container.style.backgroundColor = backGrColour;
            listbox.style.backgroundColor = backGrColour;
        }
    }        
    
    //Sets all colours of background and text in the same time
    inputControl.SetAllColours = function(txt, bckg, txtH, bckgH) {
        inputControl.SetHighlightColours(txtH, bckgH);
        inputControl.SetColours(txt, bckg);
    }
    
    //Returns the current status of geocoding operation
    inputControl.GetStatus = function() {
        return this.controlstatus;
    }
    
    //Sets the current status of geocoding operation
    inputControl.SetStatus = function(status){
        this.controlstatus = status;
    }
    
    //Starts the timer for menu scrolling according the specific direction
    inputControl.startScroll = function(dir) {
        clearInterval(this.timerId);
        var cmd = "document.getElementById('"+inputControl.id+"').scroll("+dir+")";
        this.timerId = setInterval(cmd, 100);
    }
    
    //Stops the timer for menu scrolling
    inputControl.stopScroll = function() {
        clearInterval(this.timerId);
    }
    
    //Scrolls the listbox in dir direction, an item each time
    inputControl.scroll = function(dir) {
        var listBox = document.getElementById(inputControl.id + "_chLoc_ListBox");
        var slider = document.getElementById(inputControl.id + "_scrollBar_slider");
        var offset = listBox.offsetTop;
		if (offset == 0 && dir == 0) return; // controllo per non farlo scendere troppo
		var firstLI =listBox.getElementsByTagName("li").item(0);
		var itemHeight = firstLI.clientHeight > 0 ? firstLI.clientHeight : firstLI.offsetHeight;
		var listBoxHeight = listBox.clientHeight > 0 ? listBox.clientHeight : listBox.offsetHeight;
		if (dir == 1 && (listBoxHeight + offset) <= (inputControl.maxVisibleItems * itemHeight)) return;
		
		if (dir == 0) { //up direction
			offset += itemHeight;
		} else { //down direction
			offset -= itemHeight;
		}
		slider.doStep(dir);
		listBox.style.top = offset + "px";
    }
    
    /*Creates all necessary dom nodes to build the menu, and appends the
      new menu to the textbox*/
    function createChooseLocation() {
        var container = document.createElement("div");
        container.id = inputControl.id + "_chLoc";
        container.style.width = "auto";
        container.style.height = "auto";
        container.style.backgroundColor = backGrColour;
        container.style.position = "absolute";
        container.style.top = "-10000px";
        container.style.left = "-10000px";
        container.style.textAlign = "left";
        container.style.zIndex = "200";
        //container.style.display = "none";
        container.style.fontFamily = "Verdana,Arial,Helvetica,sans-serif";
        container.style.fontSize = "0.75em";
        container.style.fontWeight = "bold";
        container.style.overflow = "hidden";
        container.style.color = txtColour;
        container.status = 0;
        
        var listBox = document.createElement("ul");
        listBox.id = inputControl.id + "_chLoc_ListBox";
        listBox.style.listStyleType = "none";
        listBox.style.position = "relative";
        listBox.style.top = "0";
        listBox.style.left = "0";
        listBox.style.width = "100%";
        listBox.style.padding = "0 2px";
        container.appendChild(listBox);
        
        var scrollBar = document.createElement("div");
        scrollBar.id = inputControl.id + "_scrollBar";
        scrollBar.style.width = "18px";
        scrollBar.style.height = "100%";
        scrollBar.style.backgroundColor = "transparent";
        scrollBar.style.position = "absolute";
        scrollBar.style.top = "-10000px";
        scrollBar.style.right = "0";
        scrollBar.style.zIndex = container.style.zIndex + 1;
        container.appendChild(scrollBar);
        
        var arrowUp = document.createElement("img");
        arrowUp.id = scrollBar.id + "_up";
        arrowUp.setAttribute("src", "/master/resourcesNew/img/bt_ud_def.png");
        arrowUp.style.display = "block";
        arrowUp.style.position = "absolute";
        arrowUp.style.top = "0";
        arrowUp.style.right = "0";
        arrowUp.style.cursor = "pointer";
        arrowUp.style.margin = "0";
        arrowUp.style.padding = "0";
        arrowUp.onmousedown = function() {inputControl.startScroll(0);};
        arrowUp.onmouseup = function() {inputControl.stopScroll();};
        scrollBar.appendChild(arrowUp);
        
        var arrowDw = document.createElement("img");
        arrowDw.id = scrollBar.id + "_down";
        arrowDw.setAttribute("src", "/master/resourcesNew/img/bt_down_def.png");
        arrowDw.style.display = "block";
        arrowDw.style.position = "absolute";
        arrowDw.style.bottom = "0";
        arrowDw.style.right = "0";
        arrowDw.style.cursor = "pointer";
        arrowDw.style.margin = "0";
        arrowDw.style.padding = "0";
        arrowDw.onmousedown = function() {inputControl.startScroll(1);};
        arrowDw.onmouseup = function() {inputControl.stopScroll();};
        scrollBar.appendChild(arrowDw);
        
        var slider = document.createElement("div");
        slider.id = scrollBar.id + "_slider";
        slider.style.width = "15px";
        slider.style.height = "50%";
        slider.style.position = "absolute";
        slider.style.top = arrowUp.height + "px";
        slider.style.backgroundColor = "#36CB36";
        slider.style.border = "1px outset #36CB36";
        slider.minOffsetTop = arrowUp.height;
        slider.realTop = arrowUp.height;
        slider.doStep = function(dir) {
            var newTop;
            if (dir == 0) {
                slider.realTop -= slider.stepSize;
            } else {
                slider.realTop += slider.stepSize;
            }
            newTop = Math.round(slider.realTop);
            if (newTop < slider.minOffsetTop) newTop = slider.minOffsetTop;
			slider.style.top =  newTop + "px";
        }
        scrollBar.insertBefore(slider, arrowDw);
        
        
        if (inputControl.nextSibling) {
            inputControl.parentNode.insertBefore(container, inputControl.nextSibling);
        } else {
            inputControl.parentNode.appendChild(container);
        }
    }
    
    //--default colours---
    var backGrColour = "#DEF17E";
    var txtColour = "#187418";
    inputControl.SetColours("#187418", "#DEF17E");
    var bckgrHighColour = txtColour;
    var txtHighColour = backGrColour;
    
    //---status
    var controlstatus = GUI.AAAGeoCodingMenu.EMPTY;
    controlstatus;
    txtColour;
    
    //default error messages
    inputControl.locNotFound = "Impossibile trovare il luogo specificato";
    inputControl.geocodeFail = "Servizio momentaneamente non disponibile";
}

//SIDE AND DIRECTION CONSTANTS
GUI.AAAGeoCodingMenu.LEFT = 0;
GUI.AAAGeoCodingMenu.RIGHT = 1;
GUI.AAAGeoCodingMenu.UP = 0;
GUI.AAAGeoCodingMenu.DOWN = 1;
//STATUS CONTROL CONSTANTS
GUI.AAAGeoCodingMenu.EMPTY = 1;
GUI.AAAGeoCodingMenu.FILLED = 2;
GUI.AAAGeoCodingMenu.READY = 3;
GUI.AAAGeoCodingMenu.ERROR = -1;

//Computes absolute position of the given object (respect to page body)
function elementPosition(obj) {
	var left = 0;
	var top = 0;
	
	if(obj.offsetParent != null && obj.offsetParent && obj.offsetParent != "undefined") {
	    do {
		    left += obj.offsetLeft;
		    top += obj.offsetTop;
		    try{
                if(obj.offsetParent.scrollLeft)	
                    left-= obj.offsetParent.scrollLeft;
                if(obj.offsetParent.scrollTop)
	                top-= obj.offsetParent.scrollTop;
	            }
	         catch(a){/*non fare una fava*/}
	    }while (obj = obj.offsetParent);
	}

	
	return {x:left, y:top};
};